#pragma once

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define SIZE 1024
#define PATHNAME "/tmp"
#define PROJID 0x4321

#define CREATE_NEW_MSGQUEUE (IPC_CREAT | IPC_EXCL | 0666)
#define GET_MSGQUEUE (IPC_CREAT)

typedef struct
{
    long mtype;
    char mtext[SIZE];
} msg_t;

class MsgQueueBase
{
public:
    MsgQueueBase() {}

    bool BuildMsgQueue(int flg)
    {
        _key = ::ftok(PATHNAME, PROJID);
        if (_key < 0)
            exit(1);
        _msgid = ::msgget(_key, flg);
        if (_msgid < 0)
            exit(2);
        return true;
    }

    bool SendMessage(const std::string &in, long type)
    {
        msg_t msg;
        msg.mtype = type;
        memset(msg.mtest, 0, sizeof(msg.mtext));
        strncpy(msg.mtext, &msg, in.size());
        int n = msgsnd(_msgid, &msg, in.size(), 0);
        if (n < 0)
            return false;
        return true;
    }
    bool RecvMessage(std::string *out, long type)
    {
        msg_t msg;
        int n = ::msgrcv(_msgid, &msg, SIZE, type, 0);
        if (n < 0)
            return false;
        msg.mtext[n] = 0; // 当做字符串
        *out = msg.mtext;
        return true;
    }
    bool DeleteMsgQueue()
    {
        int n = ::msgctl(_msgid, IPC_RMID, nullptr);
        return n == 0;
    }

protected:
    key_t _key;
    int _msgid;
}

class MsgQueueClient : public MsgQueueBase
{
public:
    MsgQueueClient()
    {
        bool res = MsgQueueBase::BuildMsgQueue(GET_MSGQUEUE); // 获取
        (void)res;
    }
};

class MsgQueueServer : public MsgQueueBase
{
public:
    MsgQueueServer()
    {
        bool res = MsgQueueBase::BuildMsgQueue(CREATE_NEW_MSGQUEUE); // 创建
        (void)res;
    }
    ~MsgQueueServer()
    {
        bool res = MsgQueueBase::DeleteMsgQueue();
        (void)res;
    }
};

#define SERVER 1
#define CLIENT 2
